W4. Полные и неполные FSA, операции над FSA (дополнение, пересечение, объединение, разность), FST, регулярные языки, свойства замкнутости

Автор

Manuel Mazzara

Дата публикации

13 февраля 2026 г.

1. Краткое содержание

1.1 Представления конечных автоматов

На предыдущих лекциях мы изучили формальное определение конечного автомата (FSA). Теперь рассмотрим два важных варианта задания функции переходов: полные и неполные FSA.

1.1.1 Полные FSA

Полный FSA — это автомат, у которого функция переходов \(\delta\) всюду определена (total): она задана для каждой пары «состояние — входной символ». Формально, для полного FSA \(M = (Q, \Sigma, \delta, q_0, F)\) функция \(\delta: Q \times \Sigma \to Q\) должна удовлетворять:

\[\forall q \in Q, \forall \sigma \in \Sigma: \delta(q, \sigma) \text{ определена}\]

То есть в каком бы состоянии ни находился автомат и какой бы символ он ни прочитал, всегда есть определённый переход в некоторое состояние (в том числе в то же самое через петлю).

Зачем нужна полнота? Полный FSA гарантирует, что любую строку над алфавитом можно обработать, не «застревая». У автомата всегда есть однозначное конечное состояние — принимающее или отвергающее.

Пример: FSA над алфавитом \(\{0, 1\}\) с двумя состояниями \(q_0\) (принимающее) и \(q_1\) (непринимающее):

  • Из \(q_0\): на входе 0 → остаёмся в \(q_0\), на входе 1 → переход в \(q_1\)
  • Из \(q_1\): на входе 0 → переход в \(q_0\), на входе 1 → остаёмся в \(q_1\)

Это полный автомат: для каждой пары \((q, \sigma)\) переход задан.

1.1.2 Неполные FSA

Неполный FSA (также частичный FSA) — автомат, у которого функция \(\delta\) частична: для некоторых пар «состояние — символ» переход не задан. Формально:

\[\exists q \in Q, \exists \sigma \in \Sigma: \delta(q, \sigma) \text{ не определена}\]

Что происходит при неопределённом переходе? Если при разборе строки FSA попадает в ситуацию, где \(\delta(q, \sigma)\) не определена, строка автоматически отвергается — автомат не может продолжить работу и достичь принимающего состояния.

Пример: FSA над алфавитом \(\{a, b\}\):

  • \(q_0\) (старт) → на a переход в \(q_1\); на b переход не определён
  • \(q_1\) (принимающее) → на b остаёмся в \(q_1\); на a не определено

Этот FSA принимает строки вида «a», за которым следует ноль или больше символов b (\(\{ab^k : k \geq 0\}\)). Строка, начинающаяся с b, или содержащая a после первой позиции, приводит к неопределённому переходу и отвергается.

Графическое представление: на диаграммах неполные FSA просто не рисуют стрелок для неопределённых переходов. У полных FSA показаны все переходы.

1.1.3 Превращение неполного FSA в полный

Любой неполный FSA можно преобразовать в эквивалентный полный, добавив состояние-ловушку (ошибочное состояние, сток). Процедура:

  1. Добавить новое непринимающее состояние \(q_{\text{trap}}\) (или \(q_E\) — от «error»)
  2. Для каждого неопределённого \(\delta(q, \sigma)\) задать переход в ловушку: \(\delta(q, \sigma) = q_{\text{trap}}\)
  3. Петли в ловушке по всем символам: \(\delta(q_{\text{trap}}, \sigma) = q_{\text{trap}}\) для всех \(\sigma \in \Sigma\)

Свойство ловушки: войдя в неё, автомат уже не выйдет. Так как она непринимающая, любая строка, приводящая в неё, отвергается.

Пример: дополнение неполного FSA выше:

  • Добавить \(q_{\text{trap}}\) (непринимающее)
  • \(q_0\) на b\(q_{\text{trap}}\)
  • \(q_1\) на a\(q_{\text{trap}}\)
  • \(q_{\text{trap}}\) на a\(q_{\text{trap}}\)
  • \(q_{\text{trap}}\) на b\(q_{\text{trap}}\)

Теперь для каждой пары «состояние — символ» переход определён: FSA полон, а распознаваемый язык тот же.

1.2 Регулярные языки

Регулярный язык — любой язык, который может быть распознан (принят) конечным автоматом. Это базовое понятие теоретической информатики.

Формальное определение: язык \(L \subseteq \Sigma^*\) называется регулярным тогда и только тогда, когда существует конечный автомат \(M = (Q, \Sigma, \delta, q_0, F)\) такой, что \(L = L(M)\), где:

\[L(M) = \{w \in \Sigma^* : \delta^*(q_0, w) \in F\}\]

То есть \(L\) состоит ровно из тех строк, которые при обработке \(M\) приводят в принимающее состояние.

Важные свойства регулярных языков:

  1. Разрешимость: для любого регулярного \(L\) и любой строки \(w\) алгоритмически можно проверить, принадлежит ли \(w \in L\), моделируя FSA
  2. Конечность описания: регулярные языки задаются FSA с конечным числом состояний
  3. Свойства замкнутости: регулярные языки замкнуты относительно многих операций (объединение, пересечение, дополнение, конкатенация, звезда Клини)

Примеры регулярных языков:

  • \(L_1 = \{w \in \{0,1\}^* : w \text{ содержит чётное число единиц}\}\) (регулярный)
  • \(L_2 = \{w \in \{a,b\}^* : w \text{ начинается с } a\}\) (регулярный)
  • \(L_3 = \{a^n b^n : n \geq 0\}\) (не регулярный — нужен «счёт», недоступный FSA)
1.3 Операции над конечными автоматами

Одно из сильных свойств регулярных языков — их замкнутость относительно ряда операций: если применить такую операцию к регулярным языкам, результат снова регулярный. Для результирующих языков можно систематически построить FSA.

1.3.1 Дополнение

Задача: дан FSA \(M = (Q, \Sigma, \delta, q_0, F)\), принимающий язык \(L\); построить FSA для дополнения \(L^c = \Sigma^* \setminus L\) (все строки, не входящие в \(L\)).

Идея: чтобы принимать «противоположный» язык, инвертируем множество принимающих состояний (раньше принималось — теперь Reject, и наоборот).

Построение для полных FSA:

Для полного FSA \(M = (Q, \Sigma, \delta, q_0, F)\) автомат дополнения:

\[M^c = (Q, \Sigma, \delta, q_0, F^c)\]

где \(F^c = Q \setminus F\) (состояния, которые в \(M\) не были принимающими).

Все прочие компоненты автомата не меняются — обновляется только множество принимающих состояний.

Пример: FSA над \(\{a\}\) с состояниями \(q_0, q_1\):

  • \(M\): \(q_0 \xrightarrow{a} q_1 \xrightarrow{a} q_0\), \(F = \{q_1\}\) (нечётная длина)
  • \(M^c\): те же переходы, но \(F^c = \{q_0\}\) (чётная длина, включая \(\epsilon\))

Почему это верно? В полном FSA каждая строка заканчивается в некотором состоянии. Если оно было принимающим в \(M\), в \(M^c\) хотим отвергать — делаем непринимающим; если было непринимающим — делаем принимающим.

Критично: полнота

Простой приём «поменять принимающие состояния» работает только для полных FSA. Почему?

В неполном FSA часть строк обрывается на неопределённом переходе и тем самым неявно отвергается. Поменяв только принимающие состояния, мы меняем судьбу лишь строк, которые полностью обработаны. Строки, отвергнутые из‑за неопределённости, этим приёмом не учитываются.

Построение для неполных FSA:

  1. Сначала сделать FSA полным, добавив ловушку для всех неопределённых переходов
  2. Затем поменять принимающие состояния: \(F^c = Q \setminus F\)

Пример: неполный FSA: \(q_0 \xrightarrow{a} q_1\) (принимающее), \(q_1 \xrightarrow{b} q_1\) над \(\{a, b\}\).

Шаг 1: добавить ловушку \(q_2\):

  • \(q_0\) на b\(q_2\)
  • \(q_1\) на a\(q_2\)
  • \(q_2\) на a, b\(q_2\)

Шаг 2: дополнение. Было \(F = \{q_1\}\), значит \(F^c = \{q_0, q_2\}\).

Автомат дополнения принимает все строки, кроме тех, что начинаются с a и дальше содержат только b.

1.3.2 Пересечение

Задача: даны FSA \(M_1\) и \(M_2\) для языков \(L_1\) и \(L_2\); построить FSA для \(L_1 \cap L_2\) (строки, входящие в оба языка).

Идея: запускаем оба FSA параллельно на одной входной строке. Принимаем только если приняли бы оба автомата по отдельности.

Построение (прямое произведение):

Пусть

  • \(M_1 = (Q_1, \Sigma, \delta_1, q_0^1, F_1)\)
  • \(M_2 = (Q_2, \Sigma, \delta_2, q_0^2, F_2)\)

Тогда автомат пересечения:

\[M_1 \cap M_2 = (Q, \Sigma, \delta, q_0, F)\]

где:

  • \(Q = Q_1 \times Q_2\) (декартово произведение: пары состояний)
  • \(q_0 = (q_0^1, q_0^2)\)
  • \(\delta((q, p), a) = (\delta_1(q, a), \delta_2(p, a))\) (одновременный переход в обоих)
  • \(F = \{(q, p) \in Q_1 \times Q_2 : q \in F_1 \land p \in F_2\}\) (принимают оба)

Интуиция: состояние \((q, p)\) значит «\(M_1\) в \(q\) и \(M_2\) в \(p\)». Читаем символ — обновляем обе компоненты. Принимаем, когда обе — в своих принимающих состояниях.

Пример:

\(M_1\) принимает строки нечётной длины (над \(\{a\}\)):

  • Состояния: \(q_0, q_1\)
  • Переходы: \(q_0 \xrightarrow{a} q_1\), \(q_1 \xrightarrow{a} q_0\)
  • \(F_1 = \{q_1\}\)

\(M_2\) принимает все строки (над \(\{a\}\)):

  • Состояния: \(p_0\)
  • Переходы: \(p_0 \xrightarrow{a} p_0\)
  • \(F_2 = \{p_0\}\)

Произведение \(M_1 \cap M_2\):

  • Состояния: \((q_0, p_0), (q_1, p_0)\)
  • Переходы: \((q_0, p_0) \xrightarrow{a} (q_1, p_0)\), \((q_1, p_0) \xrightarrow{a} (q_0, p_0)\)
  • \(F = \{(q_1, p_0)\}\) (\(q_1 \in F_1\) и \(p_0 \in F_2\))

Принимаются строки нечётной длины (как у \(M_1\), так как \(M_2\) всё пропускает).

Размер: при \(|Q_1| = n\), \(|Q_2| = m\) в произведении \(n \times m\) состояний. Не все достижимы из начального — часто можно упростить, удаляя недостижимые.

1.3.3 Объединение

Задача: даны \(M_1\), \(M_2\) для \(L_1\), \(L_2\); построить FSA для \(L_1 \cup L_2\) (строки из хотя бы одного языка).

Построение:

Почти то же, что пересечение, но другое множество принимающих:

\[M_1 \cup M_2 = (Q, \Sigma, \delta, q_0, F)\]

где:

  • \(Q = Q_1 \times Q_2\)
  • \(q_0 = (q_0^1, q_0^2)\)
  • \(\delta((q, p), a) = (\delta_1(q, a), \delta_2(p, a))\)
  • \(F = \{(q, p) \in Q_1 \times Q_2 : q \in F_1 \lor p \in F_2\}\) (хотя бы одна компонента принимающая)

Отличие от пересечения только в условии принятия: логическое ИЛИ (\(\lor\)) вместо И (\(\land\)).

Пример: те же \(M_1\), \(M_2\):

  • \(F = \{(q_0, p_0), (q_1, p_0)\}\) (так как \(p_0 \in F_2\), обе пары подходят)
  • Начальное \((q_0, p_0)\) принимающее — принимается даже \(\epsilon\)
  • Принимаются все строки (как у \(M_2\))

Альтернатива через законы де Моргана:

\[L_1 \cup L_2 = \overline{\overline{L_1} \cap \overline{L_2}}\]

то есть «НЕ (НЕ \(L_1\) И НЕ \(L_2\))» = принимается хотя бы одним.

1.3.4 Разность

Задача: построить FSA для \(L_1 \setminus L_2\)\(L_1\), но не в \(L_2\)).

Построение:

Снова прямое произведение:

\[M_1 \setminus M_2 = (Q, \Sigma, \delta, q_0, F)\]

где:

  • \(Q = Q_1 \times Q_2\)
  • \(q_0 = (q_0^1, q_0^2)\)
  • \(\delta((q, p), a) = (\delta_1(q, a), \delta_2(p, a))\)
  • \(F = \{(q, p) \in Q_1 \times Q_2 : q \in F_1 \land p \notin F_2\}\) (\(M_1\) принимает и \(M_2\) не принимает)

Интуиция: принимаем, когда «\(M_1\) да» и «\(M_2\) нет».

Пример: \(M_1\) — нечётная длина, \(M_2\) — все строки.

  • \(L_1 \setminus L_2 = \emptyset\)\(L_1\), но не во «всём» — пусто)
  • \(F = \emptyset\) (нет \((q, p)\) с \(p \notin F_2\), так как \(F_2 = \{p_0\}\) и везде \(p = p_0\))

Обратный пример: \(M_2 \setminus M_1\) (все строки кроме нечётной длины):

  • \(F = \{(q_0, p_0)\}\) (\(p_0 \in F_2\), \(q_0 \notin F_1\))
  • Принимаются строки чётной длины (включая \(\epsilon\))
1.4 Конечные преобразователи (FST)

Finite State Transducer (FST) обобщает FSA, добавляя выход: FSA лишь принимает или отвергает строки, FST преобразует входную строку в выходную.

1.4.1 Формальное определение

FST — кортеж:

\[T = (Q, I, \delta, q_0, F, O, \eta)\]

где:

  • \((Q, I, \delta, q_0, F)\) — обычный FSA («компонента распознавания»)
  • \(O\)выходной алфавит
  • \(\eta: Q \times I \to O^*\)выходная функция: на каждом переходе выдаётся строка выходных символов (возможно пустая)

Важно:

  1. Преобразование только для принятых строк: если базовый FSA строку не принимает, выхода нет (или преобразователь «падает»)
  2. На каждом переходе может быть выход: из \(q\) по входу \(\sigma\) выдаётся \(\eta(q, \sigma)\)
  3. Выход может быть пустым (\(\epsilon\))

На диаграммах: переходы подписываются как \(i/o\), где \(i\) — входной символ, \(o\) — выходная строка.

1.4.2 Пример: удаление нечётных вхождений 0 и удвоение 1

Задача: FST над \(A = \{0, 1\}\), который:

  • принимает строки с чётным числом нулей
  • на выходе:
    • каждое нечётное по счёту 0 удаляет (выход \(\epsilon\))
    • каждое чётное 0 оставляет (выход 0)
    • каждую 1 удваивает (выход 11)

Примеры:

  • Вход: 010010 → Выход: 110110
  • Вход: 00 → Выход: 0
  • Вход: 000100011 → Выход: 011001111

Построение FST:

  • Состояния:
    • \(q_0\) (принимающее): «видели чётное число нулей»
    • \(q_1\): «видели нечётное число нулей»
  • Переходы и выходы:
    • \(q_0 \xrightarrow{1/11} q_0\)
    • \(q_0 \xrightarrow{0/\epsilon} q_1\)
    • \(q_1 \xrightarrow{1/11} q_1\)
    • \(q_1 \xrightarrow{0/0} q_0\)
  • Принимающие: \(F = \{q_0\}\)

Как работает: чётность числа нулей кодируется состоянием; для 1 выход всегда 11; для 0\(\epsilon\) или 0 в зависимости от нечётного/чётного вхождения.

1.4.3 Применения FST
  • Текст: поиск-замена, орфография
  • Обработка естественного языка: морфология (например walkedwalk)
  • Компиляторы: шаблоны исходного кода → целевой код
  • Сжатие: кодирование/декодирование
  • Замена по регулярным выражениям: в духе s/pattern/replacement/g
1.5 Свойства замкнутости регулярных языков

Семейство языков \(\mathcal{L}\) замкнуто относительно операции OP, если из \(L_1, L_2 \in \mathcal{L}\) следует \(L_1 \text{ OP } L_2 \in \mathcal{L}\).

Смысл замкнутости (closure): как у «замкнутой системы» — выполняя разрешённые операции, мы не выходим из класса. Для regular languages ряд операций снова даёт регулярный язык.

Регулярные языки замкнуты относительно:

  1. Объединения: \(L_1 \cup L_2\) (прямое произведение)
  2. Пересечения: \(L_1 \cap L_2\) (прямое произведение)
  3. Дополнения: \(\overline{L}\) (смена принимающих в полном FSA)
  4. Разности: \(L_1 \setminus L_2\) (прямое произведение)
  5. Конкатенации: \(L_1 \cdot L_2 = \{xy : x \in L_1, y \in L_2\}\)
  6. Звезды Клини: \(L^* = \bigcup_{k=0}^{\infty} L^k\)

Зачем это нужно:

  1. Композиция: собираем сложные регулярные языки из простых
  2. Доказательство регулярности: зная, что \(L_1\), \(L_2\) регулярны, сразу знаем, что \(L_1 \cup L_2\) регулярен, не строя FSA
  3. Компиляторы: комбинирование шаблонов для лексики

Пример: \(L = \{w \in \{0,1\}^* : w \text{ имеет чётное число нулей или нечётное число единиц}\}\) регулярен, потому что:

  • \(L_1 = \{w : w \text{ имеет чётное число нулей}\}\) регулярен
  • \(L_2 = \{w : w \text{ имеет нечётное число единиц}\}\) регулярен
  • \(L = L_1 \cup L_2\) по замкнутости относительно объединения
1.6 Практика: упрощение FSA

При построении FSA операциями пересечения/объединения часто появляются недостижимые состояния — те, в которые нельзя попасть из начального. Их можно удалить без смены языка.

Пример: при \(|Q_1| = 3\), \(|Q_2| = 4\) в произведении 12 состояний, но не все пары \((q, p)\) достижимы из \((q_0^1, q_0^2)\).

Алгоритм упрощения:

  1. Пометить начальное состояние как достижимое
  2. Итеративно помечать состояния, достижимые из уже помеченных по любому переходу
  3. Удалить все непомеченные состояния и связанные с ними переходы

Это снижает размер автомата в реализациях.


2. Определения

  • Полный FSA: конечный автомат, у которого \(\delta: Q \times \Sigma \to Q\) всюду определена: для всех \(q \in Q\), \(\sigma \in \Sigma\) значение \(\delta(q, \sigma)\) задано.
  • Неполный FSA (частичный FSA): автомат с частичной \(\delta\); строки, доходящие до неопределённого перехода, автоматически отвергаются.
  • Состояние-ловушка (ошибочное, сток): непринимающее состояние, добавляемое для дополнения неполного FSA; все бывшие «дыры» ведут в ловушку, в ловушке — петли по всем символам; войдя, не выходим; строки в ловушке отвергаются.
  • Регулярный язык: \(L \subseteq \Sigma^*\), распознаваемый некоторым FSA; эквивалентно: существует FSA \(M\) с \(L = L(M)\).
  • Дополнение языка: для \(L\) над \(\Sigma\) дополнение \(L^c\) (или \(\overline{L}\)) — все строки над \(\Sigma\), не входящие в \(L\): \(L^c = \Sigma^* \setminus L\).
  • Пересечение языков: \(L_1 \cap L_2 = \{w \in \Sigma^* : w \in L_1 \land w \in L_2\}\) (общий алфавит).
  • Объединение языков: \(L_1 \cup L_2 = \{w \in \Sigma^* : w \in L_1 \lor w \in L_2\}\).
  • Разность языков: \(L_1 \setminus L_2 = \{w \in \Sigma^* : w \in L_1 \land w \notin L_2\}\).
  • Прямое произведение автоматов: объединение \(M_1\) и \(M_2\) в один FSA с состояниями-парами \((q,p)\), \(q \in Q_1\), \(p \in Q_2\); параллельная симуляция на одном входе.
  • Декартово произведение множеств: \(A \times B = \{(a, b) : a \in A, b \in B\}\).
  • Finite State Transducer (FST): расширение FSA выходной строкой; формально \(T = (Q, I, \delta, q_0, F, O, \eta)\), \(O\) — выходной алфавит, \(\eta: Q \times I \to O^*\) — выходная функция.
  • Выходная функция (\(\eta\)): в FST задаёт выходную строку (возможно \(\epsilon\)) при переходе из состояния по входному символу.
  • Свойство замкнутости: семейство \(\mathcal{L}\) замкнуто относительно операции, если из \(L_1,\ldots \in \mathcal{L}\) результат операции снова в \(\mathcal{L}\). Регулярные языки замкнуты относительно объединения, пересечения, дополнения, разности, конкатенации и звезды Клини.
  • Недостижимое состояние: состояние, в которое нельзя попасть из начального ни по какой цепочке переходов; удаление не меняет распознаваемый язык.

3. Формулы

  • Дополнение FSA (полный): для полного \(M = (Q, \Sigma, \delta, q_0, F)\) имеем \(M^c = (Q, \Sigma, \delta, q_0, F^c)\), \(F^c = Q \setminus F\)
  • Пересечение FSA (прямое произведение): для \(M_1 = (Q_1, \Sigma, \delta_1, q_0^1, F_1)\) и \(M_2 = (Q_2, \Sigma, \delta_2, q_0^2, F_2)\) автомат \(M_1 \cap M_2 = (Q, \Sigma, \delta, q_0, F)\), где:
    • \(Q = Q_1 \times Q_2\)
    • \(q_0 = (q_0^1, q_0^2)\)
    • \(\delta((q, p), a) = (\delta_1(q, a), \delta_2(p, a))\)
    • \(F = \{(q, p) \in Q_1 \times Q_2 : q \in F_1 \land p \in F_2\}\)
  • Объединение FSA (прямое произведение): как пересечение, но \(F = \{(q, p) \in Q_1 \times Q_2 : q \in F_1 \lor p \in F_2\}\)
  • Разность FSA (прямое произведение): как пересечение, но \(F = \{(q, p) \in Q_1 \times Q_2 : q \in F_1 \land p \notin F_2\}\)
  • Законы де Моргана для языков: \(L_1 \cup L_2 = \overline{\overline{L_1} \cap \overline{L_2}}\) и \(L_1 \cap L_2 = \overline{\overline{L_1} \cup \overline{L_2}}\)

4. Примеры

4.1. Построение FST: прошедшее время → настоящее (Лаба 4, Задание 1)

Постройте полный FST над алфавитом \(A = \{w, t, a, l, k, e, d\}\), который:

  • принимает только глаголы walked или talked
  • переводит глагол в форму настоящего времени (убирает окончание ed)
Показать решение

Ключевая идея: FST читает посимвольно и выдаёт нужный выход. Для walkedwalk выводим каждую букву, кроме финальных ed.

fst_walked start q0 q0 start->q0 q1 q1 q0->q1 w/w t/t q2 q2 q1->q2 a/a q3 q3 q2->q3 l/l q4 q4 q3->q4 k/k q5 q5 q4->q5 e/ε q6 q6 q5->q6 d/ε

FST: пример морфологического перевода (англ.) walked/talked → walk/talk

  1. Состояния:
    • \(q_0\) (старт): ещё ничего не прочитано
    • \(q_1\): прочитано w или t
    • \(q_2\): wa или ta
    • \(q_3\): wal или tal
    • \(q_4\): walk или talk
    • \(q_5\): walke или talke
    • \(q_6\) (принимающее): полностью walked или talked
    • \(q_{\text{trap}}\): ошибка для неверного ввода
  2. Переходы и выходы:
    • Из \(q_0\): w → выход w, в \(q_1\); t → выход t, в \(q_1\); иначе в ловушку
    • Из \(q_1\): aa, в \(q_2\); иначе ловушка
    • Из \(q_2\): ll, в \(q_3\); иначе ловушка
    • Из \(q_3\): kk, в \(q_4\); иначе ловушка
    • Из \(q_4\): e\(\epsilon\), в \(q_5\) (не выводим e)
    • Из \(q_5\): d\(\epsilon\), в \(q_6\) (не выводим d)
    • \(q_6\) — принимающее
    • \(q_{\text{trap}}\) (непринимающее): любой «неверный» символ ведёт в ловушку с выходом \(\epsilon\); из ловушки по каждому символу алфавита \(A\) — петля в ловушку с выходом \(\epsilon\)

Проверка:

  • Вход: walked → Выход: walk
  • Вход: talked → Выход: talk

Ответ: FST с состояниями \(q_0,\ldots,q_6\) и переходами как выше; на выходе все символы кроме финальных e и d.

4.2. Построение FST: стирание каждой второй a (Лаба 4, Задание 2)

Постройте полный FST над \(A = \{a, b\}\), который:

  • принимает только строки, оканчивающиеся на b
  • на выходе стирает каждое второе вхождение символа a
Показать решение

Ключевая идея: отслеживать чётность числа уже прочитанных a. На нечётных вхождениях выводить a, на чётных — \(\epsilon\). Символ b всегда выводить.

fst_every_second_a start q0 q0 start->q0 q1 q1 q0->q1 a/a q2 q2 q0->q2 b/b q1->q0 a/ε q3 q3 q1->q3 b/b q2->q2 b/b q2->q3 a/a q3->q2 a/ε q3->q3 b/b

FST: каждая вторая a стирается, строка должна оканчиваться на b

  1. Состояния:
    • \(q_0\) (старт): чётное число a, последний символ не b
    • \(q_1\): нечётное число a, последний не b
    • \(q_2\) (принимающее): чётное число a, строка оканчивается на b
    • \(q_3\) (принимающее): нечётное число a, оканчивается на b
  2. Переходы и выходы:
    • Из \(q_0\): a → выход a, в \(q_1\); bb, в \(q_2\)
    • Из \(q_1\): a\(\epsilon\), в \(q_0\); bb, в \(q_3\)
    • Из \(q_2\): aa, в \(q_3\); bb, остаёмся в \(q_2\)
    • Из \(q_3\): a\(\epsilon\), в \(q_2\); bb, остаёмся в \(q_3\)
  3. Принимающие: \(F = \{q_2, q_3\}\)

Проверка:

  • aaabaab
  • aabbabb

Ответ: четыре состояния, чётность a и факт окончания на b, выходы как выше.

4.3. FSA для чётного числа единиц и нечётного числа нулей (Лаба 4, Задание 3)

Пусть \(A = \{0, 1\}\).

Задача 1: полный FSA \(M_1\) для \[L_1 = \{x \in A^* : x \text{ содержит чётное число единиц}\}\]

Задача 2: полный FSA \(M_2\) для \[L_2 = \{x \in A^* : x \text{ содержит нечётное число нулей}\}\]

Показать решение

Ключевая идея: двумя состояниями кодировать чётность счёта; чтение отслеживаемого символа переключает состояние.

parity_pair cluster_m1 M1: чётное число единиц cluster_m2 M2: нечётное число нулей start1 q0 q0 start1->q0 q0->q0 0 q1 q1 q0->q1 1 q1->q0 1 q1->q1 0 start2 p0 p0 start2->p0 p0->p0 1 p1 p1 p0->p1 0 p1->p0 0 p1->p1 1

Два FSA по чётности: чётное число единиц и нечётное число нулей

(a) FSA для чётного числа единиц (\(M_1\)):

  1. Состояния: \(q_0\) (старт, принимающее) — чётное число единиц; \(q_1\) — нечётное
  2. Переходы: из \(q_0\): 0 — петля, 1 — в \(q_1\); из \(q_1\): 0 — петля, 1 — в \(q_0\)
  3. \(F = \{q_0\}\)

Проверка: ""\(q_0\) ✓; 11 ✓; 101 ✓; 1

(b) FSA для нечётного числа нулей (\(M_2\)):

  1. Состояния: \(p_0\) (старт) — чётное число нулей; \(p_1\) (принимающее) — нечётное
  2. Переходы: из \(p_0\): 1 — петля, 0 — в \(p_1\); из \(p_1\): 1 — петля, 0 — в \(p_0\)
  3. \(F = \{p_1\}\)

Ответ: \(M_1\): \(\{q_0,q_1\}\), принимает \(q_0\); \(M_2\): \(\{p_0,p_1\}\), принимает \(p_1\).

4.4. Комбинирование FSA: объединение, пересечение, разность (Лаба 4, Задание 4)

Используя \(M_1\) и \(M_2\) из Примера 4.3:

Задача 3: полный FSA для случая, когда принимает \(M_1\) ИЛИ \(M_2\) (объединение).

Задача 4: полный FSA, когда принимают оба (пересечение).

Задача 5: полный FSA, когда \(M_1\) принимает и \(M_2\) отвергает (разность).

Задача 6: дополнение для \(M_1\).

Показать решение

Ключевая идея: для объединения, пересечения и разности — прямое произведение; для дополнения — смена принимающих состояний у полного \(M_1\).

product_ops start qp00 (q0,p0) start->qp00 qp01 (q0,p1) qp00->qp01 0 qp10 (q1,p0) qp00->qp10 1 qp01->qp00 0 qp11 (q1,p1) qp01->qp11 1 qp10->qp00 1 qp10->qp11 0 qp11->qp01 1 qp11->qp10 0

Прямое произведение: объединение, пересечение и разность

(Задача 3) Объединение: \(M_1 \cup M_2\)

  1. Прямое произведение:
    • \(Q = \{q_0, q_1\} \times \{p_0, p_1\} = \{(q_0, p_0), (q_0, p_1), (q_1, p_0), (q_1, p_1)\}\)
    • Начальное: \((q_0, p_0)\)
    • Переходы: \(\delta((q, p), \sigma) = (\delta_1(q, \sigma), \delta_2(p, \sigma))\)
  2. Принимающие (хотя бы одна компонента принимающая): \(F = \{(q, p) : q \in \{q_0\} \lor p \in \{p_1\}\}\) \(F = \{(q_0, p_0), (q_0, p_1), (q_1, p_1)\}\)

Ответ: FSA объединения имеет 4 состояния и 3 принимающих: \((q_0, p_0), (q_0, p_1), (q_1, p_1)\).

(Задача 4) Пересечение: \(M_1 \cap M_2\)

  1. То же произведение
  2. Принимающие (обе компоненты принимающие): \(F = \{(q, p) : q \in \{q_0\} \land p \in \{p_1\}\}\) \(F = \{(q_0, p_1)\}\)

Ответ: FSA пересечения — 4 состояния, одно принимающее: \((q_0, p_1)\).

(Задача 5) Разность: \(M_1 \setminus M_2\)

  1. То же произведение
  2. Принимающие (\(M_1\) принимает, \(M_2\) отвергает): \(F = \{(q, p) : q \in \{q_0\} \land p \notin \{p_1\}\}\) \(F = \{(q, p) : q = q_0 \land p = p_0\}\) \(F = \{(q_0, p_0)\}\)

Ответ: FSA разности — 4 состояния, одно принимающее: \((q_0, p_0)\).

(Задача 6) Дополнение: \(M_1^c\)

  1. \(M_1\) уже полон (есть переходы по всем входам)
  2. Смена принимающих состояний: Исходно \(F = \{q_0\}\) Дополнение \(F^c = \{q_0, q_1\} \setminus \{q_0\} = \{q_1\}\)

Ответ: у \(M_1^c\) те же состояния и переходы, что у \(M_1\), но \(F = \{q_1\}\) (принимается нечётное число единиц).

4.5. Дополнение неполного FSA (Лаба 4, Задание 5)

Постройте дополнение для неполного FSA над \(\{0,1\}\):

  • \(q_0\) (старт, принимающее): петля на 1, по 0 в \(q_1\)
  • \(q_1\): по 0 в \(q_0\); переход по 1 не определён
Показать решение

Ключевая идея: сначала дополнить ловушкой, затем поменять принимающие.

complement_incomplete start q0 q0 start->q0 q0->q0 1 q1 q1 q0->q1 0 q1->q0 0 q2 q2 ловушка q1->q2 1 q2->q2 0,1

Дополнение неполного FSA: сначала ловушка, затем дополнение

  1. Ловушка \(q_2\): \(q_1\) на 1\(q_2\); петли \(q_2\) на 0,1
  2. Полный FSA: \(q_0\) принимающее, \(q_1,q_2\) нет (до дополнения)
  3. Дополнение: было \(F=\{q_0\}\), \(F^c=\{q_1,q_2\}\)

Ответ: принимающие \(\{q_1,q_2\}\).

4.6. FSA для делимости на 2 и на 3 (Лаба 4, Задание 6)

\(A = \{0,1\}\); \(\epsilon\) входит в оба языка.

Задача 1: полный FSA \(M_a\) для \[L_a = \{x \in A^* : x \text{ — двоичная запись целого, делящегося на 2}\}\]

Задача 2: полный FSA \(M_b\) для \[L_b = \{x \in A^* : x \text{ — двоичная запись целого, делящегося на 3}\}\]

Показать решение

Ключевая идея: в двоичной записи делимость на 2 — по последней цифре; на 3 — по остатку при чтении слева направо.

divisibility_fsas cluster_two Делится на 2 cluster_three Делится на 3 s1 q0 q0 s1->q0 q0->q0 0 q1 q1 q0->q1 1 q1->q0 0 q1->q1 1 s2 r0 r0 s2->r0 r0->r0 0 r1 r1 r0->r1 1 r1->r0 1 r2 r2 r1->r2 0 r2->r1 0 r2->r2 1

FSA: делимость на 2 и на 3 в двоичной записи

(a) Делимость на 2: число чётно тогда и только тогда, когда последняя цифра 0 (или пустая строка как 0).

  1. \(q_0\) (старт, принимающее): последняя цифра 0 или ещё не было цифр
  2. \(q_1\): последняя цифра 1
  3. Переходы: из \(q_0\) на 0 — в \(q_0\), на 1 — в \(q_1\); из \(q_1\) на 0 — в \(q_0\), на 1 — петля

Проверка: \(\epsilon\) ✓; 10 (=2) ✓; 11 (=3) ✗

(b) Делимость на 3: отслеживаем остаток при делении на 3. Читая двоичные цифры слева направо, обновляем остаток так: \(\text{новый\_остаток} = (2 \times \text{старый\_остаток} + \text{цифра}) \bmod 3\).

  1. Состояния (остаток mod 3):

    • \(r_0\) (старт, принимающее): остаток 0 (делится на 3)
    • \(r_1\): остаток 1
    • \(r_2\): остаток 2
  2. Переходы: из состояния \(r_i\) при чтении цифры \(d\) новое состояние \(r_{(2i + d) \bmod 3}\).

    Явно:

    • Из \(r_0\): 0\(r_0\) (\((2 \cdot 0 + 0) \bmod 3 = 0\)); 1\(r_1\) (\((2 \cdot 0 + 1) \bmod 3 = 1\))
    • Из \(r_1\): 0\(r_2\) (\((2 \cdot 1 + 0) \bmod 3 = 2\)); 1\(r_0\) (\((2 \cdot 1 + 1) \bmod 3 = 0\))
    • Из \(r_2\): 0\(r_1\) (\((2 \cdot 2 + 0) \bmod 3 = 1\)); 1\(r_2\) (\((2 \cdot 2 + 1) \bmod 3 = 2\))
  3. Принимающие: \(F = \{r_0\}\)

Проверка: \(\epsilon\) → в \(r_0\) ✓; 11 (=3) ✓; 110 (=6) ✓; 10 (=2) ✗

Ответ: \(M_a\) — 2 состояния (последняя цифра 0); \(M_b\) — 3 состояния (остаток mod 3).

4.7. Комбинирование FSA делимости (Лаба 4, Задание 7)

По \(M_a\), \(M_b\) из Примера 4.6:

Задача 3: полный FSA для пересечения (делится на 2 и на 3, т.е. на 6).

Задача 4: полный FSA для объединения (делится на 2 или на 3).

Задача 5: полный FSA: \(M_a\) принимает и \(M_b\) отвергает (делится на 2, но не на 3).

Показать решение

Ключевая идея: прямое произведение с нужным условием на принимающие пары.

divisible_6 start q0r0 (q0,r0) start->q0r0 q0r0->q0r0 0 q1r1 (q1,r1) q0r0->q1r1 1 q0r1 (q0,r1) q0r2 (q0,r2) q0r2->q0r1 0 q1r2 (q1,r2) q0r2->q1r2 1 q1r0 (q1,r0) q1r0->q0r0 0 q1r0->q1r1 1 q1r1->q0r2 0 q1r1->q1r0 1

Произведение автоматов для делимости на 2 и на 3

(Задача 3) Делимость на 6: \(M_a \cap M_b\)

  1. Состояния-пары: \(Q = \{q_0, q_1\} \times \{r_0, r_1, r_2\}\) — 6 состояний. Начальное: \((q_0, r_0)\)
  2. Принимающие (делятся на 2 и на 3): \(F = \{(q,r) : q \in \{q_0\} \land r \in \{r_0\}\} = \{(q_0, r_0)\}\)

Ответ: FSA для делимости на 6 имеет 6 состояний и одно принимающее: \((q_0, r_0)\).

(Задача 4) Делимость на 2 или 3: \(M_a \cup M_b\)

  1. То же множество пар состояний
  2. Принимающие (делится на 2 ИЛИ на 3): \(F = \{(q,r) : q \in \{q_0\} \lor r \in \{r_0\}\}\) \(F = \{(q_0,r_0), (q_0,r_1), (q_0,r_2), (q_1,r_0)\}\)

Ответ: 6 состояний, 4 принимающих.

(Задача 5) Делится на 2, но не на 3: \(M_a \setminus M_b\)

  1. То же произведение
  2. Принимающие (на 2 да и на 3 нет): \(F = \{(q,r) : q \in \{q_0\} \land r \notin \{r_0\}\}\) \(F = \{(q_0,r_1), (q_0,r_2)\}\)

Ответ: 6 состояний, два принимающих: \((q_0,r_1)\) и \((q_0,r_2)\).

4.8. Сложное прямое произведение (Лаба 4, Задание 8)

Пусть \(M_1\) и \(M_2\) — полные FSA над алфавитом \(\{a, b\}\):

\(M_1\):

  • Состояния: \(A\) (старт), \(B\), \(C\) (принимающее)
  • Переходы: \(A\) — петля на b, по a в \(B\); \(B\) — петля на a, по b в \(C\); \(C\) по b в \(A\)

\(M_2\):

  • Состояния: \(X\) (старт), \(Y\), \(Z\) (принимающее)
  • Переходы: \(X\) — петля на a, по b в \(Y\); \(Y\) по a в \(X\), по b в \(Z\); \(Z\) — петли на a и b

Нарисуйте полные FSA, принимающие:

(i) \(L_1 \cup L_2\)
(ii) \(L_1 \cap L_2\)
(iii) \(L_1 \setminus L_2\)

Показать решение

Ключевая идея: прямое произведение; принимающие состояния задаются по смыслу операции.

(i) Объединение: \(L_1 \cup L_2\)

  1. Пары состояний: \(\{A, B, C\} \times \{X, Y, Z\}\) — 9 состояний. Начальное: \((A, X)\)

  2. Принимающие (хотя бы одна компонента принимающая): \(F = \{(q, p) : q = C \lor p = Z\}\)

    Явно: \((C, X), (C, Y), (C, Z), (A, Z), (B, Z)\)

  3. Переходы: \(\delta((q, p), \sigma) = (\delta_1(q, \sigma), \delta_2(p, \sigma))\) для всех пар и символов

Ответ: FSA из 9 состояний, 5 принимающих (все пары, где \(q = C\) или \(p = Z\)).

(ii) Пересечение: \(L_1 \cap L_2\)

  1. То же произведение
  2. Принимающие (обе компоненты принимающие): \(F = \{(q, p) : q = C \land p = Z\} = \{(C, Z)\}\)

Ответ: 9 состояний, одно принимающее: \((C, Z)\).

(iii) Разность: \(L_1 \setminus L_2\)

  1. То же произведение
  2. Принимающие (\(M_1\) принимает, \(M_2\) отвергает): \(F = \{(q, p) : q = C \land p \neq Z\} = \{(C, X), (C, Y)\}\)

Ответ: 9 состояний, два принимающих: \((C, X)\) и \((C, Y)\).

4.9. От диаграммы состояний к таблице переходов (Туториал 4, Пример 1)

Дан FSA в виде диаграммы переходов; постройте таблицу переходов.

Три состояния: \(q_0\) (старт), \(q_1\), \(q_2\) (принимающее), алфавит \(\{a, b\}\). Переходы:

  • \(q_0 \xrightarrow{a} q_0\), \(q_0 \xrightarrow{b} q_1\)
  • \(q_1 \xrightarrow{b} q_0\), \(q_1 \xrightarrow{a} q_2\)
  • \(q_2 \xrightarrow{a} q_2\), \(q_2 \xrightarrow{b} q_1\)
Показать решение

Ключевая идея: таблица переходов — другой способ задать FSA: строки — состояния, столбцы — символы алфавита, в ячейках — состояние назначения.

  1. Структура таблицы:
    • Строки: по одной на каждое состояние (\(q_0, q_1, q_2\))
    • Столбцы: по одному на каждый символ (\(a, b\))
    • Начальное состояние помечают \(\to\), принимающие — \(*\)
  2. Заполнение по диаграмме:
    • Из \(q_0\): a\(q_0\), b\(q_1\)
    • Из \(q_1\): a\(q_2\), b\(q_0\)
    • Из \(q_2\): a\(q_2\), b\(q_1\)

Таблица переходов:

a b
\(\to q_0\) \(q_0\) \(q_1\)
\(q_1\) \(q_2\) \(q_0\)
\(*q_2\) \(q_2\) \(q_1\)

Ответ: заполненная таблица приведена выше.

4.10. Дополнение неполного FSA до полного (Туториал 4, Пример 2)

Неполный FSA над \(\{a, b\}\):

  • \(q_0\) (старт) \(\xrightarrow{a} q_1\) (принимающее)
  • \(q_1\) (принимающее) \(\xrightarrow{b} q_1\) (петля)

Переходы \(\delta(q_0, b)\) и \(\delta(q_1, a)\) не определены. Сделайте автомат полным.

Показать решение

Ключевая идея: добавить состояние-ловушку и направить в неё все ранее неопределённые переходы.

  1. Неопределённые переходы: \(\delta(q_0, b)\), \(\delta(q_1, a)\)
  2. Добавить ловушку \(q_2\) (непринимающее)
  3. Доопределить:
    • \(q_0 \xrightarrow{b} q_2\)
    • \(q_1 \xrightarrow{a} q_2\)
  4. Петли ловушки: \(q_2 \xrightarrow{a} q_2\), \(q_2 \xrightarrow{b} q_2\)

Полный FSA:

  • Состояния: \(q_0\) (старт), \(q_1\) (принимающее), \(q_2\) (ловушка, непринимающее)
  • Переходы:
    • \(q_0 \xrightarrow{a} q_1\), \(q_0 \xrightarrow{b} q_2\)
    • \(q_1 \xrightarrow{a} q_2\), \(q_1 \xrightarrow{b} q_1\)
    • \(q_2 \xrightarrow{a} q_2\), \(q_2 \xrightarrow{b} q_2\)

Ответ: полный FSA с ловушкой \(q_2\), куда ведут все бывшие «дыры».

4.11. Дополнение полного FSA (Туториал 4, Пример 3)

Полный FSA \(M\) над \(\{a\}\):

  • \(M = \langle \{q_0, q_1\}, \{a\}, \{((q_0, a), q_1), ((q_1, a), q_0)\}, q_0, \{q_1\} \rangle\)

Он принимает строки с нечётным числом символов a. Постройте \(M^c\).

Показать решение

Ключевая идея: у полного FSA дополнение — смена принимающих и непринимающих состояний.

  1. Исходные принимающие: \(F = \{q_1\}\)
  2. Дополнение: \(F^c = Q \setminus F = \{q_0, q_1\} \setminus \{q_1\} = \{q_0\}\)
  3. \[M^c = \langle \{q_0, q_1\}, \{a\}, \{((q_0, a), q_1), ((q_1, a), q_0)\}, q_0, \{q_0\} \rangle\]

Переходы те же; меняется только \(F\) на \(F^c = \{q_0\}\).

Проверка:

  • \(M\) принимает: a, aaa, aaaaa, … (нечётная длина)
  • \(M^c\) принимает: \(\epsilon\), aa, aaaa, … (чётная длина, включая ноль)

Ответ: \(M^c\) принимает строки с чётным числом a.

4.12. Дополнение неполного FSA (Туториал 4, Пример 4)

Неполный FSA над \(\{a, b\}\):

  • \(q_0\) (старт) \(\xrightarrow{a} q_1\) (принимающее)
  • \(q_1\) \(\xrightarrow{b} q_1\) (петля)

Постройте автомат для дополнения.

Показать решение

Ключевая идея: сначала сделать автомат полным, затем взять дополнение.

  1. Ловушка \(q_2\): \(q_0 \xrightarrow{b} q_2\), \(q_1 \xrightarrow{a} q_2\), петли \(q_2\) на \(a\), \(b\)
  2. Полный FSA: состояния \(q_0, q_1, q_2\); принимающие до дополнения \(F = \{q_1\}\)
  3. Дополнение: \(F^c = \{q_0, q_1, q_2\} \setminus \{q_1\} = \{q_0, q_2\}\)

Автомат дополнения:

  • Состояния: \(q_0\) (старт, принимающее), \(q_1\) (непринимающее), \(q_2\) (принимающее)
  • Переходы как у дополненного автомата
  • Принимающие: \(\{q_0, q_2\}\)

Ответ: дополнение принимает все строки, кроме вида \(ab^k\) при \(k \geq 0\).

4.13. Пересечение двух FSA (Туториал 4, Пример 5)

Дано:

  • \(M_1 = \langle \{q_0, q_1\}, \{a\}, \delta_1, q_0, \{q_1\} \rangle\), где \(\delta_1(q_0, a) = q_1\), \(\delta_1(q_1, a) = q_0\) (нечётная длина)
  • \(M_2 = \langle \{p_0\}, \{a\}, \delta_2, p_0, \{p_0\} \rangle\), где \(\delta_2(p_0, a) = p_0\) (все строки)

Постройте \(M_1 \cap M_2\).

Показать решение

Ключевая идея: прямое произведение; принимающие — пары, в которых обе компоненты принимающие.

  1. \(Q = Q_1 \times Q_2 = \{(q_0, p_0), (q_1, p_0)\}\)
  2. Начальное: \((q_0, p_0)\)
  3. Переходы \(\delta((q, p), a) = (\delta_1(q, a), \delta_2(p, a))\):
    • \(\delta((q_0, p_0), a) = (q_1, p_0)\)
    • \(\delta((q_1, p_0), a) = (q_0, p_0)\)
  4. \(F = \{(q, p) : q \in F_1 \land p \in F_2\} = \{(q_1, p_0)\}\)

Произведение:

\[M_1 \cap M_2 = \langle \{(q_0, p_0), (q_1, p_0)\}, \{a\}, \delta, (q_0, p_0), \{(q_1, p_0)\} \rangle\]

Ответ: пересечение принимает строки нечётной длины (как \(M_1\), так как \(M_2\) принимает всё).

4.14. Пересечение более сложных FSA (Туториал 4, Пример 6)

Два FSA над \(\{a, b\}\):

\(M_1\):

  • Состояния: \(q_0\) (старт), \(q_1\), \(q_2\) (принимающее), \(q_3\)
  • Переходы: \(q_0 \xrightarrow{a} q_0\), \(q_0 \xrightarrow{b} q_1\); \(q_1 \xrightarrow{a} q_2\), \(q_1 \xrightarrow{b} q_3\); \(q_2\) — петли на \(a,b\); \(q_3\) — петли на \(a,b\)

\(M_2\):

  • Состояния: \(p_0\) (старт), \(p_1\), \(p_2\) (принимающее)
  • Переходы: \(p_0 \xrightarrow{a} p_1\), \(p_0 \xrightarrow{b} p_0\); \(p_1 \xrightarrow{a} p_2\), \(p_1 \xrightarrow{b} p_0\); \(p_2\) — петли на \(a,b\)

Постройте \(M_1 \cap M_2\) и упростите, удалив недостижимые состояния.

Показать решение

Ключевая идея: полное произведение, затем выделение достижимых состояний.

  1. Полное произведение: \(Q_1 \times Q_2\)\(4 \times 3 = 12\) состояний. Начало \((q_0, p_0)\). Принимающие: \(\{(q, p) : q \in \{q_2\} \land p \in \{p_2\}\} = \{(q_2, p_2)\}\)

  2. Примеры переходов:

    • Из \((q_0, p_0)\) по a: \((q_0, p_1)\)
    • Из \((q_0, p_0)\) по b: \((q_1, p_0)\)
    • Из \((q_1, p_1)\) по a: \((q_2, p_2)\) — достижение принимающего состояния
  3. Достижимость из \((q_0, p_0)\): чтобы попасть в \(q_2\) в \(M_1\), нужна цепочка \(q_0 \xrightarrow{b} q_1 \xrightarrow{a} q_2\); в \(p_2\) в \(M_2\)\(p_0 \xrightarrow{a} p_1 \xrightarrow{a} p_2\) (далее \(p_2\) петлит по всем символам)

    Путь для строки aaba: \((q_0, p_0) \xrightarrow{a} (q_0, p_1) \xrightarrow{a} (q_0, p_2) \xrightarrow{b} (q_1, p_2) \xrightarrow{a} (q_2, p_2)\)

  4. После удаления недостижимых остаётся упрощённый автомат пересечения.

Ответ: упрощённое пересечение принимает строки, которые одновременно доводят \(M_1\) до \(q_2\) и \(M_2\) до \(p_2\); одна из кратчайших принимаемых строк — aaba.

4.15. Объединение двух FSA (Туториал 4, Пример 7)

Используя те же \(M_1\) и \(M_2\), что в примере 4.13 (нечётная длина и все строки), постройте \(M_1 \cup M_2\).

Показать решение

Ключевая идея: то же произведение; принимающие — пары, где хотя бы одна компонента принимающая.

  1. Состояния и переходы как у пересечения:

    • \(Q = \{(q_0, p_0), (q_1, p_0)\}\)
    • Начало \((q_0, p_0)\)
    • \((q_0, p_0) \xrightarrow{a} (q_1, p_0)\), \((q_1, p_0) \xrightarrow{a} (q_0, p_0)\)
  2. \(F = \{(q, p) : q \in F_1 \lor p \in F_2\}\). Так как \(F_2 = \{p_0\}\) и во всех достижимых парах \(p = p_0\), условие \(p \in F_2\) выполняется всегда.

    Следовательно \(F = \{(q_0, p_0), (q_1, p_0)\}\) — оба состояния принимающие; начальное принимающее, значит принимается \(\epsilon\). Фактически принимаются все строки.

Ответ: \(M_1 \cup M_2\) принимает все строки над \(\{a\}\) (как \(M_2\)).

4.16. Разность двух FSA (Туториал 4, Пример 8)

Найдите \(M_1 \setminus M_2\), где \(M_1\) — нечётная длина, \(M_2\) — все строки (как выше).

Показать решение

Ключевая идея: принимающие — пары, где первая компонента принимающая, а вторая нет.

  1. Произведение: \(Q = \{(q_0, p_0), (q_1, p_0)\}\), начало \((q_0, p_0)\)
  2. \(F = \{(q, p) : q \in F_1 \land p \notin F_2\}\). Здесь \(F_1 = \{q_1\}\), \(F_2 = \{p_0\}\).
    • Для \((q_1, p_0)\): \(q_1 \in F_1\), но \(p_0 \in F_2\) — не подходит
    • Для \((q_0, p_0)\): \(q_0 \notin F_1\) — не подходит
    • Итог: \(F = \emptyset\)

Ответ: \(M_1 \setminus M_2\) — пустой язык: всё, что в \(M_1\), уже в \(M_2\).

4.17. Разность двух FSA (Туториал 4, Пример 9)

Найдите \(M_2 \setminus M_1\) (все строки минус нечётная длина).

Показать решение
  1. \(F = \{(q, p) : p \in F_2 \land q \notin F_1\}\): нужно \(p \in \{p_0\}\) и \(q \notin \{q_1\}\).
    • \((q_0, p_0)\): \(p_0 \in F_2\) ✓, \(q_0 \notin F_1\) ✓ — принимающее
    • \((q_1, p_0)\): \(q_1 \in F_1\) ✗ — не принимающее
    • Итог: \(F = \{(q_0, p_0)\}\)

Ответ: \(M_2 \setminus M_1\) принимает строки чётной длины (включая \(\epsilon\)).